package start.demo01.erupt;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 创建和启动线程的主类
 */
public class AccountWithoutSync {
	private static Account account = new Account();
	public static void main(String[] args) {
		//创建一个根据需要创建新线程的线程池，但在可用时将重新使用以前构造的线程。
		ExecutorService service =  Executors.newCachedThreadPool();
		for(int i = 0; i < 100; i++) {
			service.execute(new AddPennyTask());
		}
		service.shutdown();//等待线程池中的任务全部执行完毕,不再接收新线程

		while(!service.isTerminated());//如果所有任务在关闭后完成，则返回 true 。
			System.out.println(account.getBalance());
	}
	/**
	 * 模拟账户类
	 * @author Adan
	 *
	 */
	private static class Account{
		//显式的创建一个公平策略（确保等待时间较长的线程优先获得锁）的锁对象
		private static Lock lock = new ReentrantLock(true);
		private int balance = 0;
		public int getBalance() {
			return balance;
		}
		/**
		 * 往账户存入指定的金额
		 * @param amount 金额
		 * synchronized：一个同步方法执行之前需要加锁（互斥，排他），一次只能一个线程拿到这个锁，其它线程等待释放锁
		 * 	成员方法：锁住的就是调用这个方法的对象
		 *  静态方法：锁住的是所在类的字节码
		 *  同步代码块，可以锁住指定的对象，锁住的是所在类的字节码
		 *  Lock
		 */
		public /* synchronized */ void deposit(int amount) {
			lock.lock();
			try {
				int newBalance = balance + amount;
				Thread.sleep(2);
				balance = newBalance;
			} catch (InterruptedException e) {
				e.printStackTrace();
			}finally {//确保锁被正确的释放
				lock.unlock();
			}
		}
	}
	
	private static class AddPennyTask implements Runnable{
		@Override
		public void run() {
			account.deposit(1);
		}
	}
}
